package com.example.springboottest.example.sentinel;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import java.util.ArrayList;
import java.util.List;

/**
 * 1、当通过springboot的时候，@SentinelResource能生效，不需要手动写Entry抛出异常
 * 2、当通过main方法时候，需要添加Entry抛出异常
 */
public class SentinelTest {

    public static void main(String[] args) {
        SentinelTest sentinelTest = new SentinelTest();
        sentinelTest.initFlowRules();

        int i = 1;
        while (true) {
            sentinelTest.sayHello("" + i++);
        }
    }

    /**
     * 限流降级
     *
     * @return
     */
    @SentinelResource(value = "sayHello", blockHandler = "sayHelloExceptionHandler")
    public String sayHello(String name) {
        try (Entry entry = SphU.entry("sayHello")) {
            System.out.println("hello," + name);
        } catch (Exception ex) {
            System.out.println("被限流了");
        }
        return "hello," + name;
    }

    /**
     * 熔断降级
     *
     * @return
     */
    @SentinelResource(value = "circuitBreaker", fallback = "circuitBreakerFallback", blockHandler = "sayHelloExceptionHandler")
    public String circuitBreaker(String name) {
        if ("zhangsan".equals(name)) {
            return "hello," + name;
        }
        throw new RuntimeException("发生异常");
    }

    public String circuitBreakerFallback(String name) {
        return "服务异常，熔断降级, 请稍后重试!";
    }

    public String sayHelloExceptionHandler(String name, BlockException ex) {
        return "访问过快，限流降级, 请稍后重试!";
    }

    private void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("sayHello");
        //QPS：每秒能访问的个数
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(5);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);

        //降级规则，可以多个degradeRule rule
        //DegradeRuleManager.getRules()可以获取到已经设置的降级规则
//        List<DegradeRule> degradeRules = new ArrayList<>();
//        DegradeRule degradeRule = new DegradeRule();
//        //设置资源名称，sentinel降级都是以资源为单位进行
//        degradeRule.setResource("circuitBreaker");
//        //使用异常统计降级,分钟统计,滑动时间窗口
//        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
//        //异常数达到的数量阈值
//        degradeRule.setCount(2);
//        //熔断时间 秒级时间窗口,该值必须有且必须大于零，否则降级将无法生效
//        degradeRule.setTimeWindow(1);
//        degradeRules.add(degradeRule);
//        //重新加载限流规则，此处将覆盖原有的限流，所以如果想要不覆盖
//        //请使用DegradeRuleManager.getRules()获取到的加入到rules中
//        DegradeRuleManager.loadRules(degradeRules);
    }
}
